Drawing Text
In addition to the many routines it provides for defining and drawing both simple and complex graphic elements, QuickDraw also provides support for drawing text. You can use QuickDraw to draw characters, words, or other textual elements at any desired size and in any available font. It might seem odd that QuickDraw handles these operations, until you realize that text, like graphics, permeates the Macintosh user interface. Windows, menus, and some controls (for instance, buttons) have titles, which are essential to the user's understanding and manipulation of the application. As a result, it makes sense to treat text fundamentally as a graphic object and to assign basic text-drawing responsibilities to QuickDraw, which manages all graphics within the Macintosh system software.Although QuickDraw is ultimately responsible for drawing text on the screen, you might need to use other Toolbox managers for other text-handling needs. For example, if you want the user to be able to input and edit some small amount of text, you can use TextEdit. TextEdit provides basic text-editing capabilities, such as cutting, copying, pasting, and entering words and characters. TextEdit calls QuickDraw to display the editable text. Similarly, if your application allows the user to display text in a variety of fonts, you might need to use the Font Manager. The Font Manager supports QuickDraw by providing the character bitmaps it needs to draw text in a specified font, size, and style. For a complete description of TextEdit and the Font Manager, see Inside Macintosh: Text.
The Venn Diagrammer application has very minimal text-handling requirements. It does not support any text entry or editing by the user. Instead, it obtains all the text it needs from resources stored in its resource fork. As a result, the Venn Diagrammer application can use basic QuickDraw text-drawing routines to display its text. For example, the Venn Diagrammer application draws the message in a window's status area by calling the application-defined routine DoStatusMesg, defined in Listing 5-9.
Listing 5-9 Retrieving a status message from a resource
PROCEDURE DoStatusMesg (myWindow: WindowPtr; myMessageID: Integer); VAR myText: Str255; BEGIN GetIndString(myText, rVennD, myMessageID); DoStatusText(myWindow, myText); END;As you can see, theDoStatusMesg
routine takes two parameters, a window pointer specifying the window whose status area is to be filled in and an integer specifying the index into an'STR#'
resource. ThenDoStatusMesg
retrieves the appropriate message text and calls the application-defined procedureDoStatusText
to print the message in the window.Venn Diagrammer calls
DoStatusMesg
whenever it needs to display a message in the status area. For instance, when the user wants to determine if a syllogism is valid or not, Venn Diagrammer checks the syllogism's validity and then executes the code in
Listing 5-10.Listing 5-10 Informing the user of an argument's validity or invalidity
IF valid THEN BEGIN IF gShowNames THEN {show names of valid syllogisms?} BEGIN GetIndString(myMesg, rVennD, eArgIsValid); DoGetName(myWindow, myName); myMesg := concat(myMesg, ' (', myName, ')'); DoStatusText(myWindow, myMesg); END ELSE DoStatusMesg(myWindow, eArgIsValid); END ELSE DoStatusMesg(myWindow, eArgNotValid);This code fragment illustrates why the Venn Diagrammer application defines two different routines,DoStatusMesg
andDoStatusText
. The first,DoStatusMesg
, retrieves the desired message text from a resource and calls the second,DoStatusText
, to display it on the screen. The application also callsDoStatusText
at other times, for instance, when it needs to add something to the resource-based message string. In the example shown in Listing 5-10, the application needs to get the name of the valid syllogism, if the user has indicated that this should be done.The
DoStatusText
procedure is defined in Listing 5-11. Its job is to display the text passed as a parameter in the status area of the specified window.Listing 5-11 Displaying a status message
PROCEDURE DoStatusText (myWindow: WindowPtr; myText: Str255); VAR myRect: Rect; origSize: Integer; origFont: Integer; myHandle: MyDocRecHnd; CONST kSlop = 4; kSize = 9; kFont = applFont; BEGIN IF myWindow <> NIL THEN BEGIN SetPort(myWindow); origSize := myWindow^.txSize; {remember original size and font} origFont := myWindow^.txFont; TextSize(kSize); {set desired size and font} TextFont(kFont); SetRect(myRect, kToolWd * kNumTools, 0, myWindow^.portRect.right, kToolHt); EraseRect(myRect); IF length(myText) > 0 THEN BEGIN MoveTo(myRect.left + kSlop, myRect.bottom - kSlop); DrawString(myText); END; TextSize(origSize); {restore original size and font} TextFont(origFont); {Remember the last message printed in this window.} myHandle := MyDocRecHnd(GetWRefCon(myWindow)); myHandle^^.statusText := myText; END; END;TheDoStatusText
procedure first remembers the graphics port's existing font and size, so that it can change and then later restore those values. ThenDoStatusText
sets the desired font and size of the status message by calling the QuickDraw routinesTextFont
andTextSize
. You should always use these routines--instead of changing the fields of thegrafPort
record--whenever you want to change a graphics port's font and size.
Once it's set the desired font and size, the
- IMPORTANT
- Although you should never change the fields of a graphics port directly, you sometimes need to read those fields directly. In Listing 5-11, the original font and size are determined by reading the appropriate fields (
txFont
andtxSize
) of the graphics port record. This is necessary because QuickDraw doesn't provide routines to read that information from a graphics port record.![]()
DoStatusText
procedure callsSetRect
to define the rectangle into which the text is to be drawn. Then,DoStatusText
erases that rectangle by callingEraseRect
. If the string to be displayed consists of at least one character,DoStatusText
moves to the appropriate spot in the status area and calls the QuickDraw routineDrawString
, which draws the specified string at the current drawing location in the window.Finally,
DoStatusText
restores the graphics port's original font and size, and then copies the string just drawn into thestatusText
field of the window's document record. The Venn Diagrammer application needs to remember each window's latest status message so that it can redraw the message whenever necessary (for example, if the message is covered up by another window and then later revealed).Venn Diagrammer uses similar techniques for all other text drawing it requires. Remember that this application supports only static text (that is, text that cannot be edited) stored in the application's resource fork. To allow the user to enter and edit some text, you need to use more powerful text-handling tools. See Inside Macintosh: Text for information about using system software services like the Font Manager and TextEdit to handle editable text. See Inside Macintosh: Files for information on storing text and other data in files. Finally, see the chapter "Dialog Manager" in Inside Macintosh: Macintosh Toolbox Essentials for information on handling text entry and editing in a dialog box.